This version uses plotly.
# Standard imports
import numpy as np
#from dash import Dash, html, dash_table, dcc, callback, Output, Input
#import plotly.graph_objects as go
#from jupyter_dash import JupyterDash
#import pandas as pd
import plotly.express as px
Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions. Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.
y1 = np.array([4, 2, 3], dtype=float)
y1 /= np.linalg.norm(y1)
y2 = np.array([-1, 1, 0], dtype=float)
y2 /= np.linalg.norm(y2)
n_points = 500
A = []
for k in range(n_points):
x = 2.*np.random.randn()*y1 + np.random.randn()*y2
A.append( x + np.random.rand(3) )
A = np.array(A)
np.shape(A)
(500, 3)
fig = px.scatter_3d(x=A[:,0], y=A[:,1], z=A[:,2],
title='The cloud is like an elongated pancake')
fig.update_traces(marker_size=3)
fig.show()
U, S, VT = np.linalg.svd(A, full_matrices=False)
U.T @ U
Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.
array([[ 1.00000000e+00, 1.94289029e-16, -1.90819582e-17],
[ 1.94289029e-16, 1.00000000e+00, -1.04083409e-17],
[-1.90819582e-17, -1.04083409e-17, 1.00000000e+00]])
VT @ VT.T
Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.
array([[ 1.00000000e+00, -1.24900090e-16, -5.55111512e-17],
[-1.24900090e-16, 1.00000000e+00, 0.00000000e+00],
[-5.55111512e-17, 0.00000000e+00, 1.00000000e+00]])
S
array([49.24013109, 22.31148657, 6.36140257])
np.diag(S)
array([[49.24013109, 0. , 0. ],
[ 0. , 22.31148657, 0. ],
[ 0. , 0. , 6.36140257]])
k = 2
from copy import deepcopy
Sk = deepcopy(S)
Sk[2] = 0.
Ak = U @ np.diag(Sk) @ VT
fig = px.scatter_3d(x=Ak[:,0], y=Ak[:,1], z=Ak[:,2], title='Looking at the subspace end-on')
fig.update_traces(marker_size=2)
fig.show()
# Project points into 2D using ...
C = A @ VT[:2,:].T
# Or ...
C = U @ np.diag(Sk)
fig = px.scatter(x=C[:,0], y=C[:,1])
fig.update_traces(marker_size=5)
fig.show()